package com.xjscrm.server.service.groupsendjob.impl;

import com.baomidou.mybatisplus.core.metadata.OrderItem;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.google.common.collect.Lists;
import com.uzai.trace.TraceGenerate;
import com.xjscrm.common.annotation.MerId;
import com.xjscrm.common.entity.GroupSendJob;
import com.xjscrm.common.entity.GroupSendJobMsg;
import com.xjscrm.common.entity.GroupSendTask;
import com.xjscrm.common.utils.DateUtil;
import com.xjscrm.common.utils.Tools;
import com.xjscrm.server.biz.RatelimitService;
import com.xjscrm.server.dto.groupsendjob.GroupSendJobQuery;
import com.xjscrm.server.dto.groupsendjobmsg.GroupSendJobMsgQuery;
import com.xjscrm.server.dto.groupsendtask.GroupSendTaskQuery;
import com.xjscrm.server.mapper.GroupSendJobMapper;
import com.xjscrm.server.mapper.GroupSendJobMsgMapper;
import com.xjscrm.server.mapper.GroupSendTaskMapper;
import com.xjscrm.server.service.groupsendjob.GroupSendJobService;
import com.xjscrm.server.service.groupsendjob.GroupSendJobSyncService;
import com.xjscrm.server.service.groupsendjob.GroupSendTaskSyncService;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.lang3.StringUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.scheduling.annotation.Async;
import org.springframework.stereotype.Service;

import java.time.LocalDate;
import java.time.LocalDateTime;
import java.time.LocalTime;
import java.time.ZoneId;
import java.util.Date;
import java.util.List;
import java.util.concurrent.TimeUnit;

/**
 * 群发任务异步实现类
 *
 * @author makejava
 * @since 2024-03-01 17:01:12
 */
@Slf4j
@Service
public class GroupSendJobSyncServiceImpl implements GroupSendJobSyncService {

    @Autowired
    private RedisTemplate redisTemplate;
    @Autowired
    private GroupSendTaskMapper groupSendTaskMapper;
    @Autowired
    private RatelimitService ratelimitService;
    @Autowired
    private GroupSendJobService groupSendJobService;
    @Autowired
    private GroupSendJobMapper groupSendJobMapper;
    @Autowired
    private GroupSendJobMsgMapper groupSendJobMsgMapper;

    /**
     * 处理群发任务的消息
     * @param merId
     * @return null
     * @author jitwxs
     * @date 2024/3/8 17:12
     */
    @Async("taskExecutorForXxJob")
    @TraceGenerate //注入消息id标签
    public void groupSendJobSendMsg(@MerId Long merId){
        //限流key
        String taskLimitKet = "-groupSendJobSendMsg-taskLimitKey-merId=" + merId;
        Object object = redisTemplate.opsForValue().get(taskLimitKet);
        if (object == null) {
            //保存限流key
            redisTemplate.opsForValue().set(taskLimitKet, taskLimitKet, 300, TimeUnit.SECONDS);
        }else{
            return;
        }

        try {
            //查询当前所有开启的自动发圈的配置方案
            int now = DateUtil.getTime();

            GroupSendJobQuery groupSendJobQuery = new GroupSendJobQuery();
            groupSendJobQuery.setMerId(merId);
            groupSendJobQuery.setStatus(1); //进行中
            groupSendJobQuery.setStartSendTimeEnd(now);

            //查询所有的自动发圈配置记录
            Page<GroupSendJob> page = new Page<>();
            page.setCurrent(1);//只查第一页
            page.setSize(10); //每页查询10个
            page.addOrder(OrderItem.asc("id"));//默认id升序
            Long idStart = 0L;
            List<GroupSendJob> groupSendJobList = groupSendJobMapper.findByList(page, groupSendJobQuery);
            while (groupSendJobList != null && groupSendJobList.size() > 0) {
                for (GroupSendJob groupSendJob : groupSendJobList) {
                    if (groupSendJob.getId().longValue() >idStart.longValue()) {
                        idStart = groupSendJob.getId();
                    }

                    //限流判断
                    String rateLimitKey = "groupSendJobSendMsg-jobId=" + groupSendJob.getId();
                    Object rateLimitKeyobject = redisTemplate.opsForValue().get(rateLimitKey);
                    if (rateLimitKeyobject == null) {
                        //保存限流key
                        redisTemplate.opsForValue().set(rateLimitKey, rateLimitKey, 300, TimeUnit.SECONDS);
                    } else {
                        continue;
                    }

                    try {

                        //判断此任务是否还有未发送的消息，如果没有了，则修改成已完成
                        GroupSendJobMsgQuery groupSendJobMsgQuery = new GroupSendJobMsgQuery();
                        groupSendJobMsgQuery.setMerId(merId);
                        groupSendJobMsgQuery.setJobId(groupSendJob.getId());
                        groupSendJobMsgQuery.setStatus(1); //查询该机器人还是否有未发送的消息
                        Integer count = Tools.getInteger(groupSendJobMsgMapper.findCount(groupSendJobMsgQuery));
                        if(count.intValue() == 0 && Tools.getInteger(groupSendJob.getStartSendTime().intValue()) < now - 180){//此任务已经没有未发送的消息，将任务修改成已完成
                            groupSendJob.setStatus(2);//状态（1-发送中；2-已完成；3-已暂停；4-已取消)
                            groupSendJob.setUpdateTime(DateUtil.getTime());
                            groupSendJobMapper.updateById(groupSendJob);
                            continue;
                        }

                        //处理群发任务的消息
                        groupSendJobService.groupSendJobSendMsg(groupSendJob);

                    } catch (Exception e) {
                        log.info("--封装群发任务消息失败--error={}", e.getMessage());
                    }finally {
                        //保存成功之后，手动删除限流redisKey
                        redisTemplate.delete(rateLimitKey);
                    }
                }

                groupSendJobQuery.setIdStart(idStart);
                groupSendJobList = groupSendJobMapper.findByList(page, groupSendJobQuery);
            }
        } catch (Exception e) {
            log.error(e.getMessage(), e);
        } finally {
            //删除限流key
            redisTemplate.delete(taskLimitKet);
        }

    }
}
